package com.lhf.aicloud.utils;

import org.springframework.lang.NonNull;

import java.util.concurrent.*;

/**
 * @author lhf
 * 线程池工具类
 */
public class ThreadPoolUtils {
    // 系统可用计算资源
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();

    // 核心线程数
    private static final int CORE_POOL_SIZE = Math.max(4, Math.min(CPU_COUNT - 1, 8));

    // 最大线程数
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;

    // 空闲线程存活时间
    private static final int KEEP_ALIVE_SECONDS = 30;

    // 工作队列
    private static final BlockingQueue<Runnable> POOL_WORK_QUEUE = new LinkedBlockingQueue<>(128);

    // 工厂模式
    private static final MyThreadFactory MY_THREAD_FACTORY = new MyThreadFactory();

    // 饱和策略
    private static final ThreadRejectedExecutionHandler THREAD_REJECTED_EXECUTION_HANDLER =
            new ThreadRejectedExecutionHandler.CallerRunsPolicy();

    // 线程池对象
    private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR;

    static {
        THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAXIMUM_POOL_SIZE,
                KEEP_ALIVE_SECONDS,
                // 空闲线程执行时间单位
                TimeUnit.SECONDS,
                // 工作队列（或者阻塞队列）
                POOL_WORK_QUEUE,
                MY_THREAD_FACTORY,
                THREAD_REJECTED_EXECUTION_HANDLER
        );
    }

    private ThreadPoolUtils() {
    }

    public static synchronized ThreadPoolExecutor getInstance() {
        return THREAD_POOL_EXECUTOR;
    }
}


class MyThreadFactory implements ThreadFactory {
    @Override
    public Thread newThread(@NonNull Runnable r) {
        return new Thread(r);
    }
}


class ThreadRejectedExecutionHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        // 由具体子类负责实现
    }

    /**
     * 饱和策略一：调用者线程执行策略，即：在调用者中执行被拒绝任务的run方法，除非线程池shutdown，否则直接丢弃线程
     */
    public static class CallerRunsPolicy extends ThreadRejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            // 如果线程池正在运行，则由调用者线程执行被拒绝的任务。如果线程池停止运行，则直接丢弃该任务。
            if (!executor.isShutdown()) {
                r.run();
            }
        }
    }

    /**
     * 饱和策略二：终止策略，丢弃被拒绝的任务，并抛出拒绝执行异常
     */
    public static class AbortPolicy extends ThreadRejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            throw new RejectedExecutionException("请求任务：" + r.toString() + "，线程池负载过高执行饱和终止策略。");
        }
    }

    /**
     * 饱和策略三：丢弃策略，什么都不做直接丢弃被拒绝的任务
     */
    public static class DiscardPolicy extends ThreadRejectedExecutionHandler {
    }

    /**
     * 饱和策略四：丢弃策略，丢弃最早加入阻塞队列的线程，并尝试将被拒绝的任务加入阻塞队列
     */
    public static class DiscardOldPolicy extends ThreadRejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            // 如果线程池正常运行，则弹出或者丢弃最早放入阻塞队列中的任务，并尝试将拒绝执行的任务加入阻塞队列
            if (!executor.isShutdown()) {
                executor.getQueue().poll();
                executor.execute(r);
            }
        }
    }
}
